<?php
/**
 * Provides a set of data about the http request to the controller
 * 
 * @author Alan Moreau - moreau.alan@gmail.com
 *
 */
class Mac_Controller_HTTPRequest
{
    private $controller = '';
    private $module = '';
    private $action = '';
    
    private $params = array();
    
	public function __construct ()
	{
	    $requestURI = $this->getRequestURI();
	    if($requestURI !== '/'){
	       $module = $this->definesMCA($requestURI);
	    }
	}
	
	/**
	 * 
	 */
	public function isPostRequest ()
	{
		return isset($_SERVER['REQUEST_METHOD']) 
			&& !strcasecmp($_SERVER['REQUEST_METHOD'],'POST');
	}

	/**
	 * 
	 * 
	 */
	public function isAjaxRequest ()
	{
		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) 
			&& $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
	}
	
	public function getPost ($key=null)
	{
        if ($key !== null) {
            return isset($_POST[$key]) ? $_POST[$key] : null;
        } else {
            return $_POST;
        }
	}
	
	public function getParam ($key)
	{
		return isset($this->params[$key]) ? $this->params[$key] : null;
	}
	
	public function getRequestURI ()
	{
		return $_SERVER['REQUEST_URI'];
	}
	
	private function setMCA ($module, $controller, $action)
	{
	    $this->module = $module;
	    $this->controller = $controller;
	    $this->action = $action;
	}
	
	private function definesMCA ($requestURI)
	{
	    $urlParts = explode('/', $requestURI);
	    array_shift($urlParts); //shift first empty value 
	    
	    $module = array_shift($urlParts);
	    if(file_exists(MODULES_PATH . '/'.$module)){
	        $this->module = $module;
	    }
	    
	    $controller = '';
	    if($this->module !== '' && !empty($urlParts)){
	       $controller = array_shift($urlParts);
	    } else {
	        $controller = $module;
	    }
	    
	    $this->controller = $this->rewriteUrlElement($controller);
	    
	    if(!empty($urlParts)){
	        $action = array_shift($urlParts);
	        $this->action = $this->rewriteUrlElement($action);
	    }
        
        if (strstr($requestURI, '?') !== false) {
            header('Location: '.$this->rewriteUrlGetParams($requestURI));
            die;
        }
	    
        $params = (count($urlParts)>0) ? explode('/-', implode('/', $urlParts)) : array();
        $orderedParams = isset($params[0]) ? explode('/', $params[0]) : array();
        $unorderedParams = isset($params[1]) ? explode('/', $params[1]) : array();
        
        foreach($orderedParams as $key => $value) {
            $this->params[$key] = $value;
        }
        $nbUnorderedParams = floor(count($unorderedParams)/2);
        for($i=0; $i<$nbUnorderedParams; $i++) {
            $key = $unorderedParams[2*$i];
            $value = explode(',', urldecode($unorderedParams[2*$i+1]));
            $this->params[$key] = (count($value)>1) ? $value : $value[0];
        }
	}
	
	private function rewriteUrlElement ($urlEncodeElement)
	{
	    $elements = explode('-', $urlEncodeElement);
	    $result = '';
	    if(count($elements) > 1){
	        foreach($elements as $e){
	            $result .= ucfirst($e);
	        }
	    } else if(!empty($elements)){
	        $element = array_pop($elements); 
	        $result = ucfirst($element);
	    }
	    
	    return $result;
	}
    
    /**
     * Rewrite the GET parameters to clean the URL
     * 
     * @param string $requestURI URI formatted : ?param1=foo1&param2=foo2
     * @return string Rewrited URL
     */
    private function rewriteUrlGetParams ($requestURI)
    {
        if(strpos($requestURI, '?') === false) {
            return $requestURI;
        } else {
            $splitedURI = explode('?', $requestURI);
            $uri = $splitedURI[0];
            $params = end($splitedURI);
            $splitedParams = explode('&', $params);
            $matches = array();
            $newUri = array();
            foreach($splitedParams as $completeParam) {
                if(preg_match('#^([a-z]+[a-z0-9])*(\[\])?=(.*)$#i', urldecode($completeParam), $matches)) {
                    $key = $matches[1];
                    $isArray = ($matches[2] === '[]');
                    $value = $matches[3];
                    if($value != '') {
                        if($isArray === true) {
                            if(isset($newUri[$key])) {
                                $newUri[$key][] = $value;
                            } else {
                                $newUri[$key] = array($value);
                            }
                        } else {
                            $newUri[$key] = $value;
                        }
                    }
                }
            }
            array_walk($newUri, function(&$value){
                if (is_array($value)) {
                    $value = implode(',', $value);
                }
            });
            $returnUrl = (count($newUri)>0) ? $uri.'/-' : $uri;
            foreach($newUri as $key => $value) {
                $returnUrl .= urlencode($key).'/'.urlencode($value).'/';
            }
            return substr($returnUrl, 0, -1);
        }
    }
    
    public function getModuleName ()
    {
        return $this->module;
    }
    
    public function getControllerName ()
    {
        return $this->controller;
    }
    
    public function getActionName ()
    {
        return $this->action;
    }
    
    public function setModuleName ($module)
    {
        $this->module = $module;
    }
    
    public function setControllerName ($controller)
    {
        $this->controller = $controller;
    }
    
    public function setActionName ($action)
    {
        $this->action = $action;
    }
    
    public function getParams ()
    {
        return $this->params;
    }
    
    public function setParams (array $params)
    {
        $this->params = $params;
    }
    
    public function addParam ($value, $key = null)
    {
        if($key !== null){
            $this->params[$key] = $value;
        } else {
            $this->params[] = $value;
        }
    }
    
    public function getOrderedParams ()
    {
        $params = array();
        foreach($this->params as $key => $param) {
            if (is_int($key)) {
                $params[] = $param;
            }
        }
        return $params;
    }
    
    public function getUnorderedParams ()
    {
        $params = array();
        foreach($this->params as $key => $param) {
            if (!is_int($key)) {
                $params[$key] = $param;
            }
        }
        return $params;
    }
}
